package com.yiyuan.app.service.impl;

import com.guaike.core.entity.result.Result;
import com.guaike.core.redis.context.ApiContext;
import com.guaike.core.utils.DateUtil;
import com.yiyuan.app.dao.*;
import com.yiyuan.app.entity.enums.DetailsTypeEnum;
import com.yiyuan.app.entity.enums.LabelTypeEnum;
import com.yiyuan.app.entity.enums.PrizeActionEnum;
import com.yiyuan.app.entity.param.DealSignDTO;
import com.yiyuan.app.entity.po.*;
import com.yiyuan.app.entity.result.AppUser;
import com.yiyuan.app.entity.result.BaseSignVO;
import com.yiyuan.app.entity.result.SignVO;
import com.yiyuan.app.service.BaseUtilService;
import com.yiyuan.app.service.SignService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

@Slf4j
@Service
@AllArgsConstructor
public class SignServiceImpl implements SignService {
    private final UAppUserDAO uAppUserDAO;
    private final UAppUserEquityDAO uAppUserEquityDAO;
    private final MConfPrizeDAO mConfPrizeDAO;
    private final MConfPrizeRuleDAO mConfPrizeRuleDAO;
    private final BaseUtilService baseUtilService;
    private final MRecordSignDAO mRecordSignDAO;
    private final MRecordSignDetailDAO mRecordSignDetailDAO;
    private final DDetailsPineconeDAO dDetailsPineconeDAO;

    @Override
    public Result<SignVO> signPageInfo() {
        AppUser currentUser = ApiContext.getCurrentUser();
        SignVO result = new SignVO();
        MConfPrizePO prizePO;
        if (baseUtilService.checkNewSign()) {
            prizePO = mConfPrizeDAO.findOne(MConfPrizePO::getAction, PrizeActionEnum.new_sign.getCode());
        } else if (baseUtilService.checkSign()) {
            prizePO = mConfPrizeDAO.findOne(MConfPrizePO::getAction, PrizeActionEnum.sign.getCode());
        } else {
            return Result.failure().message("签到活动已到期").build();
        }
        List<MConfPrizeRulePO> rulePOS = mConfPrizeRuleDAO.findList(MConfPrizeRulePO::getPrizeId, prizePO.getId(), MConfPrizeRulePO::getSignDay, Boolean.TRUE);
        result.setAction(prizePO.getAction());
        result.setName(prizePO.getTaskName());
        result.setTotalDays(rulePOS.size());
        List<BaseSignVO> signVOS = new ArrayList<>();
        Boolean flag = Boolean.TRUE;
        MRecordSignPO recordSignPO = mRecordSignDAO.findLatestOne(currentUser.getUserId(), prizePO.getId());
        if (Objects.nonNull(recordSignPO) && recordSignPO.getAction().equals(PrizeActionEnum.sign.getCode())) {
            MRecordSignDetailPO detailPO = mRecordSignDetailDAO.findLatestAlreadySign(currentUser.getUserId(), recordSignPO.getId());
            if (DateUtil.days(detailPO.getCreateTime().toLocalDate(), LocalDate.now()) > 1) {
                rulePOS.forEach(rulePO -> {
                    BaseSignVO vo = new BaseSignVO();
                    BeanUtils.copyProperties(rulePO, vo);
                    vo.setRuleId(rulePO.getId());
                    signVOS.add(vo);
                });
                result.setRuleId(rulePOS.get(0).getId());
                result.setSignVOS(signVOS);
                return Result.success().data(result).build();
            } else if (DateUtil.days(detailPO.getCreateTime().toLocalDate(), LocalDate.now()) == 0) {
                result.setAlreadySign(Boolean.TRUE);
            }
            if (!detailPO.getSignDay().equals(result.getTotalDays())) {
                result.setSignDays(detailPO.getSignDay());
            } else {
                flag = Boolean.FALSE;
            }
        } else if (Objects.nonNull(recordSignPO) && recordSignPO.getAction().equals(PrizeActionEnum.new_sign.getCode())) {
            MRecordSignDetailPO detailPO = mRecordSignDetailDAO.findLatestAlreadySign(currentUser.getUserId(), recordSignPO.getId());
            if (DateUtil.days(detailPO.getCreateTime().toLocalDate(), LocalDate.now()) == 0) {
                result.setAlreadySign(Boolean.TRUE);
            }
        }
        AtomicInteger signDays = new AtomicInteger(0);
        Boolean finalFlag = flag;
        rulePOS.forEach(rulePO -> {
            BaseSignVO vo = new BaseSignVO();
            BeanUtils.copyProperties(rulePO, vo);
            vo.setRuleId(rulePO.getId());
            if (finalFlag || result.getAlreadySign()) {
                if (Objects.nonNull(recordSignPO)) {
                    MRecordSignDetailPO detailPO = mRecordSignDetailDAO.findAlreadySign(currentUser.getUserId(), recordSignPO.getId(), rulePO.getSignDay());
                    if (Objects.nonNull(detailPO)) {
                        vo.setImage(detailPO.getImage());
                        vo.setPinecone(detailPO.getPinecone());
                        vo.setIsSign(Boolean.TRUE);
                        signDays.getAndIncrement();
                    }
                }
            }
            signVOS.add(vo);
        });
        if (!result.getAlreadySign()) {
            int days;
            if (result.getAction().equals(PrizeActionEnum.sign.getCode())) {
                if (finalFlag) {
                    days = result.getSignDays() + 1;
                } else {
                    days = 1;
                }
            } else {
                UAppUserPO userPO = uAppUserDAO.findById(currentUser.getUserId());
                days = DateUtil.days(userPO.getCreateTime().toLocalDate(), LocalDate.now()) + 1;
            }
            List<MConfPrizeRulePO> collect = rulePOS.stream().filter(rule -> rule.getSignDay().equals(days)).collect(Collectors.toList());
            result.setRuleId(collect.get(0).getId());
        }
        result.setSignDays(signDays.get());
        result.setSignVOS(signVOS);
        return Result.success().data(result).build();
    }

    @Override
    public Result<Boolean> dealSign(DealSignDTO param) {
        AppUser currentUser = ApiContext.getCurrentUser();
        MConfPrizeRulePO rulePO = mConfPrizeRuleDAO.findById(param.getRuleId());
        if (Objects.isNull(rulePO)) {
            return Result.failure().message("此签到天数不存在").build();
        }
        MConfPrizePO prizePO = mConfPrizeDAO.findById(rulePO.getPrizeId());
        MRecordSignPO recordSignPO = mRecordSignDAO.findLatestOne(currentUser.getUserId(), prizePO.getId());
        if (PrizeActionEnum.new_sign.getCode().equals(prizePO.getAction()) && baseUtilService.checkNewSign()) {
            UAppUserPO userPO = uAppUserDAO.findById(currentUser.getUserId());
            if (DateUtil.days(userPO.getCreateTime().toLocalDate(), LocalDate.now()) != rulePO.getSignDay() - 1) {
                return Result.failure().message("签到天数不正确").build();
            }
            if (Objects.isNull(recordSignPO)) {
                recordSignPO = new MRecordSignPO();
                recordSignPO.setPrizeId(prizePO.getId());
                recordSignPO.setUserId(currentUser.getUserId());
                recordSignPO.setAction(prizePO.getAction());
                mRecordSignDAO.save(recordSignPO);
            } else {
                MRecordSignDetailPO alreadySign = mRecordSignDetailDAO.findAlreadySign(currentUser.getUserId(), recordSignPO.getId(), rulePO.getSignDay());
                if (Objects.nonNull(alreadySign)) {
                    return Result.failure().message("已经签到了，请勿重复签到").build();
                }
            }
        } else if (PrizeActionEnum.sign.getCode().equals(prizePO.getAction()) && baseUtilService.checkSign()) {
            if (Objects.nonNull(recordSignPO)) {
                MRecordSignDetailPO alreadySign = mRecordSignDetailDAO.findAlreadySign(currentUser.getUserId(), recordSignPO.getId(), rulePO.getSignDay());
                if (Objects.nonNull(alreadySign) && LocalDate.now().isEqual(alreadySign.getCreateTime().toLocalDate())) {
                    return Result.failure().message("已经签到了，请勿重复签到").build();
                }
                Boolean seriesSign = baseUtilService.checkSeriesSign(currentUser.getUserId(), recordSignPO, rulePO);
                if (!seriesSign) {
                    return Result.failure().message("只能连续签到").build();
                }
            }
            if (Objects.isNull(recordSignPO) || rulePO.getSignDay() == 1) {
                recordSignPO = new MRecordSignPO();
                recordSignPO.setPrizeId(prizePO.getId());
                recordSignPO.setUserId(currentUser.getUserId());
                recordSignPO.setAction(prizePO.getAction());
                mRecordSignDAO.save(recordSignPO);
            }
        } else {
            return Result.failure().message("签到活动已到期").build();
        }
        MRecordSignDetailPO detailSign = new MRecordSignDetailPO();
        detailSign.setRecordSignId(recordSignPO.getId());
        detailSign.setUserId(currentUser.getUserId());
        detailSign.setSignDay(rulePO.getSignDay());
        detailSign.setPinecone(rulePO.getPinecone());
        detailSign.setImage(rulePO.getImage());
        mRecordSignDetailDAO.save(detailSign);
        DDetailsPineconePO sign = new DDetailsPineconePO();
        sign.setUserId(currentUser.getUserId());
        sign.setLabelType(LabelTypeEnum.sign.getCode());
        sign.setDetailsType(DetailsTypeEnum.income.getCode());
        sign.setPinecone(rulePO.getPinecone());
        dDetailsPineconeDAO.save(sign);
        uAppUserEquityDAO.addPinecone(currentUser.getUserId(), rulePO.getPinecone());
        return Result.success().data(Boolean.TRUE).build();
    }

}
